#pragma once
#include <functional>
#include <string>
#include <unistd.h>
#include <sys/epoll.h>

class Connection;
class TcpServer;


    // 管理epoll接收的文件描述符，同时维护连接的应用级缓冲区
    using Handler = std::function<void(Connection*)>;

    class Connection
    {
    public:
        Connection(int sock, uint32_t event, TcpServer* R)
            : _socket(sock), _event(event), _R(R)
        {
        }

        void SetCallBack(Handler reader, Handler writer, Handler execpter)
        {
            _reader = reader;
            _writer = writer;
            _execpter = execpter;
        }

        int GetSocket() { return _socket; }
        uint32_t GetEvent() { return _event; }
        void SetSocket(int sock) { _socket = sock; }
        void SetEvent(uint32_t event) { _event = event; }

        bool EmptyWriteBuff()
        {
            return _writebuffer.empty();
        }

        bool EmptyReadBuff()
        {
            return _readbuffer.empty();
        }

        std::string &ReadBuffer()
        {
            return _readbuffer;
        }

        std::string &WriteBuffer()
        {
            return _writebuffer;
        }

        void InReaderBuffer(std::string msg)
        {
            _readbuffer += msg;
        }

        std::string &OutReaderBuffer()
        {
            return _readbuffer;
        }

        void InWriteBuffer(std::string msg)
        {
            _writebuffer += msg;
        }

        std::string &OutWriteBuffer()
        {
            return _writebuffer;
        }

        void Close()
        {
            ::close(_socket);
        }

    private:
        // 管理文件描述符
        int _socket;
        uint32_t _event;

        // 读写缓冲区
        std::string _readbuffer;
        std::string _writebuffer;

    public:
        // 回调指针
        TcpServer *_R;
        // 处理业务回调
        Handler _reader;
        Handler _writer;
        Handler _execpter;
    };

    class ConnectionFactor
    {
    public:
        // 先补充回调方法。
         static Connection* BuildListenConnection(int sock, Handler accepter, uint32_t evt, TcpServer* R)
         {
            Connection* listen_con = new Connection(sock, evt, R);
            listen_con->SetCallBack(accepter, nullptr, nullptr);
            return listen_con;
         }

         static Connection* BuildNormalConnection(int sock, Handler reader, Handler writer, Handler excepter, uint32_t evt, TcpServer* R)
         {
            Connection* normal_con = new Connection(sock, evt, R);
            normal_con->SetCallBack(reader, writer, excepter);
            return normal_con;
         }
    };
